package com.andkrup.comm {
	import com.andkrup.events.LoaderEvent;

	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	import flash.display.DisplayObject;	
	import flash.display.LoaderInfo;	
	import flash.events.HTTPStatusEvent;	
	import flash.events.SecurityErrorEvent;	
	import flash.events.IOErrorEvent;	
	import flash.events.ProgressEvent;	
	import flash.events.Event;	
	import flash.utils.Dictionary;	
	import flash.system.ApplicationDomain;	
	import flash.system.LoaderContext;	
	import flash.net.URLRequest;	
	import flash.display.Loader;	
	
	import com.adobe.net.URI;	
	
	/**
	 * @author Andkrup
	 */
	public class ExternalDefinitionsManager extends EventDispatcher implements IExternalDefinitionsManager, ILoadListener, IEventDispatcher {
		private static var _inst : ExternalDefinitionsManager;
//		[ArrayElementType("flash.display.DisplayObject")]
		private var appDomains:Dictionary;
		
		public static function get instance():ExternalDefinitionsManager{
			if(!_inst){
				_inst = new ExternalDefinitionsManager(new ExternalDefinitionsManagerConstructor());
			}
			return _inst;
		}
		
		public function ExternalDefinitionsManager(ctr:ExternalDefinitionsManagerConstructor){
			if(!ctr){
				throw new Error("singleton error");
			}
			appDomains = new Dictionary(true);
		}
		
		public function loadExternalDefinitions(uri:URI, appDomain:ApplicationDomain = null):ApplicationDomain{
			if(appDomains[uri.toString()]){
				return (appDomains[uri.toString()] as DisplayObject).loaderInfo.applicationDomain;
			}
			var loader:Loader = new Loader();
			appDomains[uri.toString()] = loader;
			subscribeLoadListener(loader.contentLoaderInfo, this);
			var request:URLRequest = new URLRequest(uri.toString());
			if(!appDomain){
				loader.load(request);
				return null;
			}
			else{
				loader.load(request, new LoaderContext(false, appDomain));
				return null;
			}
		}
		
		public function getLoadedContent(uri:URI):DisplayObject{
			return appDomains[uri.toString()] as DisplayObject;
		}
		
		public function onLoadComplete(e:Event):void{
			var li:LoaderInfo = e.target as LoaderInfo;
			if(li){
				unsubscribeLoadListener(li, this);
				var liUri:URI = new URI(li.url);
				var uri:URI;
				for(var url:String in appDomains){
					uri = new URI(url);
					if(li.url.indexOf(url)>=0 && liUri.getFilename()==uri.getFilename()){
						appDomains[url] = li.loader.content;
						break;
					}
				}
				trace("ExternalDefinitionsManager:> onLoadComplete("+li.url+") appDomain["+uri.toString()+"]: "+li.loader.content);
				dispatchEvent(new LoaderEvent(LoaderEvent.ITEM_COMPLETE, uri, li.applicationDomain, null));
			}
		}
		public function onLoadOpen(e:Event):void{
			trace("ExternalDefinitionsManager:> onLoadOpen() tgt:"+e.target);
		}
		public function onLoadInit(e:Event):void{
			trace("ExternalDefinitionsManager:> onLoadInit() tgt:"+e.target);
		}
		public function onLoadProgress(e:ProgressEvent):void{
			trace("ExternalDefinitionsManager:> onLoadProgress() tgt:"+e.target);
		}
		public function onLoadIOError(e:IOErrorEvent):void{
			trace("ExternalDefinitionsManager:> onLoadIOError() "+e.text);
		}
		public function onLoadSecurityError(e:SecurityErrorEvent):void{
			trace("ExternalDefinitionsManager:> onLoadSecurityError() "+e.text);
		}
		public function onLoadHttpStatus(e:HTTPStatusEvent):void{
		}
	}
}
class ExternalDefinitionsManagerConstructor{}